#include <system/Keyboard.h>

namespace ne
{
    const uint32_t Keyboard::KEYBOARD_KEYS = 256;

    Keyboard::Keyboard()
        : mModifier(KM_NONE),
          mTranslationMode(KTM_OFF)
    {
        reset();
    }

    void Keyboard::setModifierUp(const KeyboardModifier km)
    {
        mModifier -= mModifier & km;
    }

    bool Keyboard::isModifierUp(const KeyboardModifier km) const
    {
        if (mModifier & km)
        {
            return false;
        }
        return true;
    }

    void Keyboard::setModifierDown(const KeyboardModifier km)
    {
        mModifier |= km;
    }

    bool Keyboard::isModifierDown(const KeyboardModifier km) const
    {
        if (mModifier & km)
        {
            return true;
        }
        return false;
    }

    uint32_t Keyboard::getModifier() const
    {
        return mModifier;
    }

    void Keyboard::setTranslationMode(const KeyboardTranslationMode ktm)
    {
        mTranslationMode = ktm;
    }

    KeyboardTranslationMode Keyboard::getTranslationMode() const
    {
        return mTranslationMode;
    }

    void Keyboard::setKeyUp(const KeyboardKey key)
    {
        mKeysDown[key] = false;
    }

    bool Keyboard::isKeyUp(const KeyboardKey key) const
    {
        return !mKeysDown[key];
    }

    void Keyboard::setKeyDown(const KeyboardKey key)
    {
        mKeysDown[key] = true;
    }

    bool Keyboard::isKeyDown(const KeyboardKey key) const
    {
        return mKeysDown[key];
    }

    void Keyboard::reset()
    {
        mModifier = KM_NONE;
        mTranslationMode = KTM_OFF;
        for (uint32_t i=0; i<KEYBOARD_KEYS; ++i)
        {
            mKeysDown[i] = false;
        }
    }

    Keyboard::~Keyboard()
    {
    }

    KeyboardKey Keyboard::ConvertASCIIKey(const uint32_t key)
    {
        switch (key)
        {
            case ASCII_NUL: return KK_UNASSIGNED;
            case ASCII_SOH: return KK_UNASSIGNED;
            case ASCII_STX: return KK_UNASSIGNED;
            case ASCII_ETX: return KK_UNASSIGNED;
            case ASCII_EOT: return KK_UNASSIGNED;
            case ASCII_ENQ: return KK_UNASSIGNED;
            case ASCII_ACK: return KK_UNASSIGNED;
            case ASCII_BEL: return KK_UNASSIGNED;
            case ASCII_BS:  return KK_BACK;
            case ASCII_HT:  return KK_TAB;
            case ASCII_LF:  return KK_UNASSIGNED;
            case ASCII_VT:  return KK_UNASSIGNED;
            case ASCII_FF:  return KK_UNASSIGNED;
            case ASCII_CR:  return KK_RETURN;
            case ASCII_SO:  return KK_UNASSIGNED;
            case ASCII_SI:  return KK_UNASSIGNED;
            case ASCII_DLE: return KK_UNASSIGNED;
            case ASCII_DC1: return KK_UNASSIGNED;
            case ASCII_DC2: return KK_UNASSIGNED;
            case ASCII_DC3: return KK_UNASSIGNED;
            case ASCII_DC4: return KK_UNASSIGNED;
            case ASCII_NAK: return KK_UNASSIGNED;
            case ASCII_SYN: return KK_UNASSIGNED;
            case ASCII_ETB: return KK_UNASSIGNED;
            case ASCII_CAN: return KK_UNASSIGNED;
            case ASCII_EM:  return KK_UNASSIGNED;
            case ASCII_SUB: return KK_UNASSIGNED;
            case ASCII_ESC: return KK_ESC;
            case ASCII_FS:  return KK_RIGHT;
            case ASCII_GS:  return KK_LEFT;
            case ASCII_RS:  return KK_UP;
            case ASCII_US:  return KK_DOWN;

            case ASCII_SP:  return KK_SPACE;
            case 0x21: return KK_1;
            case 0x22: return KK_APOSTROPHE;
            case 0x23: return KK_3;
            case 0x24: return KK_4;
            case 0x25: return KK_5;
            case 0x26: return KK_7;
            case 0x27: return KK_APOSTROPHE;
            case 0x28: return KK_9;
            case 0x29: return KK_0;
            case 0x2A: return KK_MULTIPLY;
            case 0x2B: return KK_PLUS;
            case 0x2C: return KK_COMMA;
            case 0x2D: return KK_MINUS;
            case 0x2E: return KK_DECIMAL;
            case 0x2F: return KK_DIVIDE;

            case 0x30: return KK_NUMPAD0;
            case 0x31: return KK_NUMPAD1;
            case 0x32: return KK_NUMPAD2;
            case 0x33: return KK_NUMPAD3;
            case 0x34: return KK_NUMPAD4;
            case 0x35: return KK_NUMPAD5;
            case 0x36: return KK_NUMPAD6;
            case 0x37: return KK_NUMPAD7;
            case 0x38: return KK_NUMPAD8;
            case 0x39: return KK_NUMPAD9;
            case 0x3A: return KK_SEMICOLON;
            case 0x3B: return KK_SEMICOLON;
            case 0x3C: return KK_COMMA;
            case 0x3D: return KK_EQUAL;
            case 0x3E: return KK_PERIOD;
            case 0x3F: return KK_SLASH;

            case 0x40: return KK_2;
            case 0x41: return KK_A;
            case 0x42: return KK_B;
            case 0x43: return KK_C;
            case 0x44: return KK_D;
            case 0x45: return KK_E;
            case 0x46: return KK_F;
            case 0x47: return KK_G;
            case 0x48: return KK_H;
            case 0x49: return KK_I;
            case 0x4A: return KK_J;
            case 0x4B: return KK_K;
            case 0x4C: return KK_L;
            case 0x4D: return KK_M;
            case 0x4E: return KK_N;
            case 0x4F: return KK_O;

            case 0x50: return KK_P;
            case 0x51: return KK_Q;
            case 0x52: return KK_R;
            case 0x53: return KK_S;
            case 0x54: return KK_T;
            case 0x55: return KK_U;
            case 0x56: return KK_V;
            case 0x57: return KK_W;
            case 0x58: return KK_X;
            case 0x59: return KK_Y;
            case 0x5A: return KK_Z;
            case 0x5B: return KK_LBRACKET;
            case 0x5C: return KK_BACKSLASH;
            case 0x5D: return KK_RBRACKET;
            case 0x5E: return KK_6;
            case 0x5F: return KK_UNDER;

            case 0x60: return KK_GRAVE;
            case 0x61: return KK_A;
            case 0x62: return KK_B;
            case 0x63: return KK_C;
            case 0x64: return KK_D;
            case 0x65: return KK_E;
            case 0x66: return KK_F;
            case 0x67: return KK_G;
            case 0x68: return KK_H;
            case 0x69: return KK_I;
            case 0x6A: return KK_J;
            case 0x6B: return KK_K;
            case 0x6C: return KK_L;
            case 0x6D: return KK_M;
            case 0x6E: return KK_N;
            case 0x6F: return KK_O;

            case 0x70: return KK_P;
            case 0x71: return KK_Q;
            case 0x72: return KK_R;
            case 0x73: return KK_S;
            case 0x74: return KK_T;
            case 0x75: return KK_U;
            case 0x76: return KK_V;
            case 0x77: return KK_W;
            case 0x78: return KK_X;
            case 0x79: return KK_Y;
            case 0x7A: return KK_Z;
            case 0x7B: return KK_LBRACKET;
            case 0x7C: return KK_BACKSLASH;
            case 0x7D: return KK_RBRACKET;
            case 0x7E: return KK_GRAVE;
            case ASCII_DEL: return KK_DELETE;

            default: return KK_UNASSIGNED;
        }
    }
}
